package cn.hinglo.gameclaw.data.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.Base64;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;

/**
 * @createTime: 2018/1/3
 * @author: HingLo
 * @description: 加密工具
 */
@Slf4j
public class JwtUtil {
    /**
     * 定义key
     */
    private final static String stringKey = "DE910052E696F473DB73035637DE2D8D";
    /**
     * 定义有效时间
     * 设置有效时间为3 hours
     */
    private final static int ttlMillis = 1000 * 60 * 30;

    /**
     * 由字符串生成加密key
     *
     * @return
     */
    private static SecretKey generalKey() {
        byte[] encodedKey = Base64.decodeBase64(stringKey);
        return new SecretKeySpec(encodedKey, "AES");
    }


    /**
     * 创建jwt
     *
     * @param id      唯一标识符，一般是用户的为ID
     * @param subject 保存的一些常用信息
     * @return 返回加密的token
     * @throws Exception
     */
    public static String createJWT(String id, String subject) {
        long nowMillis = System.currentTimeMillis();
        JwtBuilder builder = createJwtBuilder(id, subject);
        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            Date exp = new Date(expMillis);
            builder.setExpiration(exp);
        }
        return builder.compact();
    }

    /**
     * 创建一个不过期的token
     *
     * @param id      加密的Id
     * @param subject 加密的内容
     * @return 返回加密的token
     * @throws Exception 抛出的异常
     */
    public static String createNoJWT(String id, String subject) {
        return createJwtBuilder(id, subject).compact();
    }

    /***
     * token 的builder构建方法
     * @param id id
     * @param subject 内容
     * @return builder
     */
    private static JwtBuilder createJwtBuilder(String id, String subject) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        Date now = new Date();
        SecretKey key = generalKey();
        JwtBuilder jwtBuilder = Jwts.builder()
                .setId(id)
                .setIssuedAt(now)
                .setSubject(subject)
                .signWith(signatureAlgorithm, key);
        return jwtBuilder;
    }

    /**
     * 解密jwt
     *
     * @param token 需要解密的token
     * @return Claims 对象
     * @throws Exception 时间过期或者解密失败抛出的异常
     */
    public static Claims parseJWT(String token) {
        SecretKey key = generalKey();

        return Jwts.parser()
                .setSigningKey(key)
                .parseClaimsJws(token).getBody();
    }

    /**
     * 解密jwt 中的Id
     *
     * @param token token
     * @return Id
     * @throws Exception 时间过期或者解密失败抛出的异常
     */
    public static String parseIdJWT(String token) {
        try {
            return parseJWT(token).getId();
        } catch (Exception e) {
            //日志记录
            log.info("解密失败,错误信息如下---->{}", e.getMessage());
            //如果解密失败，就直接返回一个null
            return null;
        }

    }

}
